/**
 * Lithne.h - The official Lithne library.
 *
 * Copyright (c) 2011
 * Serge Offermans, Remco Magielse
 * {s.a.m.offermans, r.magielse}@tue.nl
 * Intelligent Lighting Institute (ILI), TU/e.
 *
 * All rights reserved. LAST UPDATE: 23-11-2011
**/

#ifndef Lithne_h
#define Lithne_h

//#include "Lithne_Config.h"

/* The following code makes the Library compatible with Arduino 1.0 */
#if defined(ARDUINO) && ARDUINO >= 100
	#include "Arduino.h"
#else
	#include "WProgram.h"
	#include "cppfix.h"
#endif

#include "XBee.h"
#include "Message.h"
#include "Node.h"
#include "LithneDefinitions.h"

/*************************** MAX_NODES
Define the number of nodes that are created
- Note that no more than MAX_NODES can be added through the AddNode() function
Default is 20
**/
#ifndef MAX_NODES
	#define MAX_NODES 20
#endif
	
/*************************** MAX_ARGS
Define the number of arguments (ints) that can be used in a message
- Note that no more than MAX_ARGS can be added through the addArgument() function
Default is 8
**/
#ifndef MAX_ARGS
	#define MAX_ARGS 20
#endif
	
/*************************** DB_MEMORY
Define the number of stored DB readings 
Default is 5
**/
#ifndef DB_MEMORY
	#define DB_MEMORY 5
#endif
enum XBEE_SERIES{S1 = 0, S2 = 1};

class LithneClass
{
  public:
	/*	Constructor and destructor	*/
	LithneClass(XBEE_SERIES series);
	~LithneClass();
	
	/*	Functions that return nothing	*/
	void init( uint32_t _baud = 115200, HardwareSerial & port = Serial );
	void begin( uint32_t _baud = 115200, HardwareSerial & port = Serial );
	void setRecipient( uint8_t _i );
	void setRecipient( XBeeAddress64 _add64 );
	void setRecipient16( uint16_t _add16 );
	void setFunction( uint8_t _function );
	void addArgument( uint16_t _arg );
	void send( );
	void send( XBeeAddress64 recipient, uint8_t function );
	void send( uint8_t id, uint8_t function );
	void sendMessage( Message * _mes );
	
	void sendDBRequest( uint8_t _id );
	void sendDBRequest( XBeeAddress64 _add64 );
	void sendDBRequest( Node * _receivingNode );
	void sendDBRequest16( uint16_t _addr16 );

	void getMyInfo();
	void setScope( uint16_t _scope );
	void addScope( uint16_t _scope );
	void joinGroup( String _group );
	void helloWorld( XBeeAddress64 _addr64 = XBeeAddress64(0x0, 0xFFFF), bool askReply = false );
	
	/*	Functions that return bits (booleans) 	*/
	bool available();
	bool addNode( uint8_t _id, XBeeAddress64 _addr64 = XBeeAddress64(0x0, 0xFFFF), uint16_t _addr16 = UNKNOWN_16B );
	bool nodeKnown( uint8_t _id );
	bool nodeKnown64( XBeeAddress64 _add64 );
	bool nodeKnown16( uint16_t _addr16 );
	bool newDBMeasurement( uint8_t _id );
	bool hasScope( uint16_t _scope );
	bool removeScope( uint16_t _scope );
	bool removeScope( String _group );
	
	/*	Functions that return bytes (8-bit integers)	*/
	uint8_t	digitalPin( uint8_t _position );
	uint8_t	pwmPin( uint8_t _position );
	uint8_t getNumberOfArguments();
	uint8_t getNumberOfNodes();
//	uint8_t getNodeId( XBeeAddress64 _add64 );							DEPRECATED getNodeBy64(_addr64)->getID();
//	uint8_t getNodeId( uint16_t _add16 );								DEPRECATED getNodeBy16(_addr16)->getID();
//	uint8_t setNodeAddress( XBeeAddress64 _add64, uint16_t _add16 );	DEPRECATED getNodeBy64(_addr64)->setAddress16(_addr16);
	
	/*	Functions that return standard integers (16-bit integers)	*/
	uint16_t getFunction();
	uint16_t getArgument( uint8_t _arg );
	uint8_t getDBs1();
//	uint16_t getDB( uint8_t _id );										DEPRECATED getNodeByID(_id)->getDB();
//	uint16_t getNodeAddress16( XBeeAddress64 _add64 );					DEPRECATED getNodeBy64(_addr64)->getAddress16();
//	uint16_t getNodeAddress16( uint8_t _nodeId );						DEPRECATED getNodeByID(_id)->getAddress16();

	uint16_t getMyAddress16( bool forceCheck = false );
	uint16_t getMyPAN( bool forceCheck = false );
	uint16_t getMyAssociationStatus( bool forceCheck = false );
	uint16_t getScope();
	uint16_t hashGroup( String _group );
	uint16_t getSender16();
	
	/*	Functions that return longs (32-bit integers)	*/
	uint32_t sendATCommand( uint8_t * cmd, uint16_t waitForResponse = 0 );
	
	/*	Functions that return Objects	*/
//	XBeeAddress64 getNodeAddress64( uint8_t _id );						DEPRECATED getNodeByID(_id)->getAddress64();
	XBeeAddress64 getSender64();
	XBeeAddress64 getMyAddress64( bool forceCheck = false );
	
	/*	Node pointer retrieval	*/
	Node * getNode( uint8_t _position );
	Node * getNodeBy64( XBeeAddress64 _addr64 );
	Node * getNodeBy16( uint16_t _addr16 );
	Node * getNodeByID( uint8_t _nodeId );
  private:
	LithneClass(); //make default constructor private, so that users are forced to use the constructor that initializes the series type

  	bool newMessage;
  	bool debugMode;
  	const XBEE_SERIES mSeries;
  	
  	void setRecipient( Node * receivingNode );
  	
  	/* These functions are only local to retrieve the position in the array */
  	uint16_t getNodeArrayPosition( uint8_t _nodeId );
	uint16_t getNodeArrayPosition( uint16_t _add16 );
	uint16_t getNodeArrayPosition( XBeeAddress64 _add64 );

  	/* Create two pointers to standard messages we use */
	Message * incomingMessage;
	Message * outgoingMessage;
	/* Create a pointer to an array of nodes with length MAX_NODES */
	Node * nodes[MAX_NODES];
	
	uint16_t scopes[MAX_SCOPES];	//Stores the HASH conversions of the groups the node belongs to
	uint16_t numNodes;				//Contains the number of nodes in storage
	uint16_t last16B;				//Stores the last 16-bit address we send a message to.
	uint16_t myAddress16;			//Stores own 16-bit address.
	uint16_t myPANid;				//Stores the PAN ID of the network
	uint16_t myAssStat;				//Stores the association status of the node
	
	XBeeAddress64	last64B;		//Stores the last 64-bit address we send a message to.
	XBeeAddress64	myAddress64;

	void readXbee ();
};

/*	Here we tell the compiler the definitions of
	all functions are given externally	*/
extern LithneClass Lithne;

#endif

